/*
 * SyncResource.java
 *
 * Created on April 12, 2007, 1:39 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.auth.service.app;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.logging.Level;
import org.atomojo.auth.service.db.AuthDB;
import org.atomojo.auth.service.db.Permission;
import org.atomojo.auth.service.db.Realm;
import org.atomojo.auth.service.db.Role;
import org.atomojo.auth.service.db.User;
import org.atomojo.auth.service.db.XML;
import org.infoset.xml.InfosetFactory;
import org.infoset.xml.ItemConstructor;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;
import org.infoset.xml.util.WriterItemDestination;
import org.restlet.Request;
import org.restlet.data.Form;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ServerResource;

/**
 *
 * @author alex
 */
public class BackupResource extends ServerResource
{
   
   long expiration = 3600*1000;
   AuthDB db;
   /** Creates a new instance of SyncResource */
   public BackupResource() {
      setNegotiated(false);
   }

   protected void doInit() {
      db = (AuthDB)getRequest().getAttributes().get(AuthApplication.DB_ATTR);
   }
   
   public Representation get()
   {
      try {
         Form form = getRequest().getResourceRef().getQueryAsForm();
         String location = form.getValues("location");
         if (location==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            return new StringRepresentation("Missing 'location' query parameter.");
         }
         File outFile = new File(location);
         if ((outFile.exists() && !outFile.canWrite()) || (!outFile.exists() && !outFile.getParentFile().canWrite())) {
            getResponse().setStatus(Status.CLIENT_ERROR_EXPECTATION_FAILED);
            return new StringRepresentation("Cannot write to file "+outFile.getAbsolutePath());
         }
         getContext().getLogger().info("Backing up to file "+outFile.getAbsolutePath());
         OutputStreamWriter w = new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8");
         ItemDestination dest = new WriterItemDestination(w,"UTF-8");
         ItemConstructor constructor = InfosetFactory.getDefaultInfoset().createItemConstructor(outFile.toURI());
         dest.send(constructor.createDocument(outFile.toURI()));
         dest.send(constructor.createElement(XML.DATABASE_NAME));
         dest.send(constructor.createCharacters("\n"));
         dest.send(constructor.createElement(XML.PERMISSIONS_NAME));
         dest.send(constructor.createCharacters("\n"));
         Iterator<Permission> permissions = db.getPermissions();
         while (permissions.hasNext()) {
            permissions.next().generate(constructor,dest);
            dest.send(constructor.createCharacters("\n"));
         }
         dest.send(constructor.createElementEnd(XML.PERMISSIONS_NAME));
         dest.send(constructor.createCharacters("\n"));
         dest.send(constructor.createElement(XML.ROLES_NAME));
         dest.send(constructor.createCharacters("\n"));
         Iterator<Role> roles = db.getRoles();
         while (roles.hasNext()) {
            roles.next().generate(constructor,dest);
            dest.send(constructor.createCharacters("\n"));
         }
         dest.send(constructor.createElementEnd(XML.ROLES_NAME));
         dest.send(constructor.createCharacters("\n"));
         dest.send(constructor.createElement(XML.USERS_NAME));
         dest.send(constructor.createCharacters("\n"));
         Iterator<User> users = db.getUsers();
         while (users.hasNext()) {
            users.next().generate(constructor,dest,true,true);
            dest.send(constructor.createCharacters("\n"));
         }
         dest.send(constructor.createElementEnd(XML.USERS_NAME));
         dest.send(constructor.createCharacters("\n"));
         dest.send(constructor.createElement(XML.REALMS_NAME));
         dest.send(constructor.createCharacters("\n"));
         Iterator<Realm> realms = db.getRealms();
         while (realms.hasNext()) {
            realms.next().generate(constructor,dest,true);
            dest.send(constructor.createCharacters("\n"));
         }
         dest.send(constructor.createElementEnd(XML.REALMS_NAME));
         dest.send(constructor.createCharacters("\n"));
         dest.send(constructor.createElementEnd(XML.DATABASE_NAME));
         dest.send(constructor.createCharacters("\n"));
         dest.send(constructor.createDocumentEnd());
         w.flush();
         w.close();
         getContext().getLogger().info("Backup finished.");
         getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
      } catch (SQLException ex) {
         getContext().getLogger().log(Level.SEVERE,"Cannot get data from database.",ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Exception while processing, see logs.");
      } catch (IOException ex) {
         getContext().getLogger().log(Level.SEVERE,"Cannot write data to output.",ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Exception while processing, see logs.");
      } catch (XMLException ex) {
         getContext().getLogger().log(Level.SEVERE,"XML error while writing data to output.",ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Exception while processing, see logs.");
      }
      return null;
   }
   
  
}
